<template>
  <div class="cftc-warp">
    <div :class="[getCheckObject.fileUrl && !isInit?'cftc-warp-left':'cftc-warp-all']">
      <!-- 输入框 -->
      <el-input style="width:100%"
                v-if="form.fieldType === 'TextField' || (isInput && form.dataType === 'String')"
                v-model="ccValue"
                :readonly="disabled || form.readonly"
                :disabled="disabled || form.readonly"
                @input="$emit('input',ccValue)"
                @change="$emit('change',ccValue);"></el-input>
      <!-- 数字输入框 -->
      <el-input-number style="text-align:left;width:100%"
                       v-else-if="form.fieldType === 'NumberField' || (isInput && (form.dataType === 'Numeric' || form.dataType === 'Integer'))"
                       :controls="false"
                       v-model="ccValue"
                       :readonly="disabled || form.readonly"
                       :disabled="disabled || form.readonly"
                       :min="Number(form.minVal)"
                       :max="Number(form.maxVal)"
                       @input="$emit('input',ccValue)"
                       @change="$emit('change',ccValue);"></el-input-number>
      <!-- 日期输入框 -->
      <template v-else-if="form.fieldType === 'DateField'">
        <el-date-picker style="width:100%"
                        v-if="form.dataType !== 'DateMinute'"
                        v-model="ccValue"
                        :type="form.dataType === 'DateYear'?'year':form.dataType === 'DateMonth'?'month':form.dataType ==='DateDay'?'date':'datetime'"
                        :value-format="form.dataType === 'DateYear'?'yyyy':form.dataType === 'DateMonth'?'yyyy-MM':form.dataType ==='DateDay'?'yyyy-MM-dd':'yyyy-MM-dd HH:mm:ss'"
                        :readonly="disabled || form.readonly"
                        :disabled="disabled || form.readonly"
                        @change="$emit('input',ccValue);$emit('change',ccValue);"
                        :picker-options="pickerOptions"
                        :placeholder="$t('common.selectDate')">
        </el-date-picker>
        <el-time-picker style="width:100%"
                        v-else-if="form.dataType === 'Datetime'"
                        v-model="ccValue"
                        format="HH:mm"
                        value-format="HH:mm"
                        :readonly="disabled || form.readonly"
                        :disabled="disabled || form.readonly"
                        @change="$emit('input',ccValue);$emit('change',ccValue);"
                        :picker-options="pickerOptions"
                        :placeholder="$t('common.selectDate')">
        </el-time-picker>
        <el-date-picker style="width:100%"
                        v-else
                        format="yyyy-MM-dd HH:mm"
                        v-model="ccValue"
                        type="datetime"
                        value-format="yyyy-MM-dd HH:mm"
                        :readonly="disabled || form.readonly"
                        :disabled="disabled || form.readonly"
                        @change="$emit('input',ccValue);$emit('change',ccValue);"
                        :picker-options="pickerOptions"
                        :placeholder="$t('common.selectDate')">
        </el-date-picker>
      </template>
      <!-- 选择框 -->
      <el-select v-else-if="form.fieldType === 'ComboBox'"
                 v-model="ccValue"
                 allow-create
                 filterable
                 clearable
                 :readonly="disabled || form.readonly"
                 :disabled="disabled || form.readonly"
                 @change="$emit('input',ccValue);$emit('change',options.filter(res=>res.value === ccValue)[0]);">
        <el-option v-for="(item,index) in options"
                   :disabled="item.disabled"
                   :key="index"
                   :label="item.label"
                   :value="item.value"></el-option>
      </el-select>
    </div>
    <el-button v-if="getCheckObject.fileUrl && !isInit"
               type="text"
               icon="el-icon-picture-outline"
               size="medium"
               @click="clickHandler"></el-button>
    <image-viewer :z-index="2000"
                  :initial-index="imageIndex"
                  v-if="showViewer"
                  :on-close="closeViewer"
                  :url-list="srcList" />
  </div>
</template>

<script>
import { getvalue, getValueByTableNameAndField } from '../../api/setting/classProperties'
import ImageViewer from 'element-ui/packages/image/src/image-viewer'
import { remote } from '../../api/admin/dict'

let prevOverflow = '';

export default {
  components: { ImageViewer },
  props: {
    value: [String, Number, Date],
    form: {
      type: Object,
      default: () => {
        return {}
      }
    },
    disabled: {
      type: Boolean,
      default: false
    },
    isInput: { // 初始化下拉框显示输入框
      type: Boolean,
      default: false
    },
    isInit: { // 初始化不显示图片
      type: Boolean,
      default: false
    },
    isDefault: { // 初始化使用默认值
      type: Boolean,
      default: true
    },
    isValid: { // 是否校验可选项
      type: Boolean,
      default: false
    },
    checkData: { // 校验数据
      type: Array,
      default: () => {
        return []
      }
    },
    checkRules: { // 变式规则
      type: Array,
      default: () => {
        return []
      }
    },
    configRules: {
      type: Array,
      default: () => {
        return []
      }
    },
    validTime: Number // 校验更新时间（用于调用其他子组件更新）
  },
  data () {
    return {
      ccValue: this.value,
      options: [],
      pickerOptions: {},
      showViewer: false
    }
  },
  computed: {
    getCheckObject () {
      const result = this.options.filter(res => res.value === this.ccValue)
      return result.length > 0 ? result[0] : {}
    },
    srcList () {
      return [this.getCheckObject.fileUrl]
    },
    imageIndex () {
      let previewIndex = 0;
      const srcIndex = this.srcList.indexOf(this.getCheckObject.fileUrl);
      if (srcIndex >= 0) {
        previewIndex = srcIndex;
      }
      return previewIndex;
    }
  },
  watch: {
    value () {
      this.ccValue = this.value
    },
    'form.fieldName': {
      immediate: true,
      handler: 'initFiled'
    },
    validTime: {
      handler: 'valid'
    }
  },
  methods: {
    clickHandler () {
      // don't show viewer when preview is false
      if (this.validatenull(this.getCheckObject)) {
        return;
      }
      // prevent body scroll
      prevOverflow = document.body.style.overflow;
      document.body.style.overflow = 'hidden';
      this.showViewer = true;
    },
    closeViewer () {
      document.body.style.overflow = prevOverflow;
      this.showViewer = false;
    },
    initFiled () {
      if (!this.form.fieldType || !this.form.dataType) return
      if (this.form.fieldType === 'DateField') {
        this.pickerOptions = {
          disabledDate: (time) => {
            return (!this.validatenull(this.form.minVal) ? new Date(this.form.minVal).getTime() >= time.getTime() : false) || (!this.validatenull(this.form.maxVal) ? new Date(this.form.maxVal).getTime() <= time.getTime() : false)
          }
        }
      }
      if (this.form.fieldType === 'ComboBox' && !this.isInput) this.getDict()
    },
    getDict () {
      if (sessionStorage.getItem('getData') !== 'false') {
        setTimeout(() => {
          this.getDict()
        }, 1);
        return
      }
      sessionStorage.setItem('getData', new Date().getTime())
      if (this.form.dictId) {
        remote({ paramId: this.form.dictId, orgId: this.form.busiFuncId }).then(res => {
          this.$set(this, 'options', res.data.data.map(res => {
            return {
              label: res.label,
              value: res.label,
              fileUrl: '',
              bucketName: '',
              fileName: '',
              disabled: false
            }
          }))
          sessionStorage.setItem('getData', 'false')
        })
      } else if (this.form.referBusiFunc) { // 引用控件
        getValueByTableNameAndField(this.form.referBusiFunc, this.form.synchTo).then(res => {
          this.options = res.data.data.map(res => {
            return {
              label: res,
              value: res,
              fileUrl: '',
              bucketName: '',
              fileName: '',
              disabled: false
            }
          })
          sessionStorage.setItem('getData', 'false')
        })
      } else if (this.form.customDataJson) { // 自定义数据
        try {
          this.options = JSON.parse(this.form.customDataJson).map(res => {
            return {
              label: res.label,
              value: res.value,
              fileUrl: res.fileUrl,
              bucketName: res.bucketName,
              fileName: res.fileName,
              disabled: false
            }
          })
          sessionStorage.setItem('getData', 'false')
        } catch (error) {
          console.error(error)
        }
      }
      else getvalue(this.form.characterId || this.form.id).then(res => {
        const data = res.data.data
        this.$set(this, 'options', data.map(res => {
          return {
            label: res.val,
            value: res.val,
            fileUrl: res.fileUrl,
            bucketName: res.bucketName,
            fileName: res.fileName,
            disabled: false
          }
        }))
        sessionStorage.setItem('getData', 'false')
        const arr = data.filter(res => res.isDefault === 1)
        if (this.validatenull(this.ccValue) && this.isDefault) this.ccValue = arr.length === 1 ? arr[0].val : ''
        this.$emit('input', this.ccValue)
      })
    },
    valid () { // 校验规则
      this.$nextTick(() => {
        try {
          if (!this.validatenull(this.ccValue)) return
          const obj = {}
          this.checkData.some(res => {
            if (this.validatenull(res.fieldVal)) return false
            if (this.validatenull(obj)) this.checkRules.some(res2 => {
              if (res2[res.characterId] === res.fieldVal) {
                for (const k in res2) {
                  if (obj[k]) obj[k].push(res2[k])
                  else obj[k] = [res2[k]]
                }
              }
            })
            else  // 查询在结果集中的位置 删除其余不存在的数据
              if (obj[res.characterId] && obj[res.characterId].length > 0)
                for (let i = obj[res.characterId].length - 1; i >= 0; i--)
                  if (obj[res.characterId][i] !== res.fieldVal)
                    for (const k in obj) obj[k].splice(i, 1)
          }) // 校验变式规则
          if (this.configRules.length > 0 && !obj[this.form.characterId]) obj[this.form.characterId] = this.options.map(res => res.value)
          if (this.validatenull(obj)) this.options.some((res, index) => { // 重置可选范围
            this.$nextTick(() => {
              this.$set(this.options, index, { ...res, disabled: false })
            })
          })
          else { // 校验配置项 并且限制可选范围
            this.checkData.some(res => {
              if (this.validatenull(res.fieldVal)) return false
              this.configRules.some(res2 => {
                const characterIds = res2.conditionList.map(res => res.characterId)
                const index = characterIds.indexOf(res.characterId)
                if (index !== -1 && this.checkAllCondition(res2.conditionList, res.fieldVal, res.dataType))
                  if (res2.conditionType === 2 || (res2.conditionType === 1 && this.checkConditionOther(res2, this.checkData))) // 判断条件是否成立
                    res2.resultList.some(res3 => {
                      if (res3.characterId === this.form.characterId)
                        for (let i = obj[res3.characterId].length - 1; i >= 0; i--)
                          obj[res3.characterId].splice(i, this.checkCondition(res3, obj[res3.characterId][i], res.dataType) ? 0 : 1)
                    })
              })
            })
            for (const k in obj) {
              if (k === `${this.form.characterId}`) {
                this.options.some((res, index) => {
                  this.$nextTick(() => {
                    this.$set(this.options, index, { ...res, disabled: Array.from(obj[k]).indexOf(res.value) === -1 })
                  })
                })
              }
            }
          }
        } catch (error) {
          console.log(error);
        }
      })
    },
    checkAllCondition (rules, value, dataType) {
      const arr = []
      rules.some(res => {
        arr.push(this.checkCondition(res, value, dataType))
      })
      return arr.indexOf(true) !== -1
    },
    checkConditionOther (rules, sourceData) { // 并且条件下判断其他值是否满足条件
      const characterIds = rules.conditionList.map(res => res.characterId)
      let result = []
      sourceData.some(res => {
        if (characterIds.indexOf(res.characterId) !== -1) {
          result.push(this.validatenull(res.fieldVal) ? false : this.checkCondition(rules.conditionList[characterIds.indexOf(res.characterId)], res.fieldVal, res.dataType))
        }
      })
      return Boolean(Array.from(new Set(result)).length > 1 ? false : Array.from(new Set(result)).join(''))
    },
    checkCondition (condition, values, dataType) {
      let check = ''
      switch (condition.operator) {
        case '=':
          check = `'${condition.attributeValue}'==='${values}'`
          break
        case '!=':
          check = `'${condition.attributeValue}'!=='${values}'`
          break
        case 'like':// 返回不等于 -1
          check = `'${values}'.indexOf('${condition.attributeValue}') !== -1 && ${!this.validatenull(values)}`
          break
        case 'lLike': // 返回坐标只能为0
          check = `'${values}'.indexOf('${condition.attributeValue}') === 0 && ${!this.validatenull(values)}`
          break
        case 'rLike': // 返回坐标只能为判断字符长度减去被判断字符长度
          check = `'${values}'.indexOf('${condition.attributeValue}') === ${values.length - condition.attributeValue.length} && ${!this.validatenull(values)}`
          break
        case '>':
        case '<':
        case '>=':
        case '<=':
          check = `${dataType === 'Numeric' || dataType === 'Integer' ? values : new Date(values).getTime()}${condition.operator}${dataType === 'Numeric' || dataType === 'Integer' ? condition.attributeValue : new Date(condition.attributeValue).getTime()}`
          break
        case 'null':
          check = `${this.validatenull(values)}`
          break
        case 'notNull':
          check = `${!this.validatenull(values)}`
          break
      }
      return eval(check)
    },
  }
}
</script>

<style lang="scss" scoped>
.cftc-warp {
  display: flex;
  flex-flow: row nowrap;
  justify-content: space-between;
  &-left {
    width: calc(100% - 40px);
  }
  &-all {
    width: 100%;
  }
}
/deep/.el-image-viewer__btn {
  color: #fff;
  font-size: 50px !important;
}
</style>